package com.olap.starter.config.dataSource;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.DataSourceProperty;
import com.baomidou.dynamic.datasource.creator.DefaultDataSourceCreator;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;

import javax.sql.DataSource;
import java.util.List;
import java.util.Map;

@Configuration
@Log4j2
public class DataSourceConfig implements ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private DataSource dataSource; // 动态数据源
    @Autowired
    private JdbcTemplate defaultJdbcTemplate;
    @Autowired
    private DefaultDataSourceCreator dataSourceCreator;
    @Autowired
    private ApplicationContext applicationContext;

    @Value("${spring.datasource.dynamic.primary:online}")
    private String defaultDbName;


    private void registerJdbcTemplateBean(String dbName, DataSource dataSource) {
        GenericApplicationContext context = (GenericApplicationContext) applicationContext;
        String beanName = dbName + "JdbcTemplate";
        if (!context.containsBean(beanName)) {
            context.registerBean(beanName, JdbcTemplate.class, () -> new JdbcTemplate(dataSource));
        }
    }

    // 获取 JdbcTemplate 时，从 Spring 容器获取
    public JdbcTemplate getJdbcTemplate(String dbName) {
        String beanName = dbName + "JdbcTemplate";
        if (applicationContext.containsBean(beanName)) {
            return (JdbcTemplate) applicationContext.getBean(beanName);
        }
        if (!dbName.equals(defaultDbName)) {
            log.warn("未找到指定数据源JdbcTemplate: {}，返回默认: {}", dbName, defaultDbName);
        }
        return defaultJdbcTemplate;
    }

    // Spring容器启动后动态注册所有数据源
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        List<Map<String, Object>> dbList = jdbcTemplate.queryForList("SELECT db_name, database_url, database_account, database_password FROM system_data_source");

        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        for (Map<String, Object> map : dbList) {
            String dbName = map.get("db_name").toString().trim();
            if (ds.getDataSources().get(dbName) != null) continue; // 已存在跳过
            DataSourceProperty dsp = new DataSourceProperty();
            dsp.setPoolName(dbName);
            dsp.setUrl(map.get("database_url").toString().trim());
            dsp.setUsername(map.get("database_account").toString().trim());
            dsp.setPassword(map.get("database_password").toString().trim());
            DataSource newDs = dataSourceCreator.createDataSource(dsp);
            ds.addDataSource(dbName, newDs);
            registerJdbcTemplateBean(dbName, newDs);
            log.info("动态注册数据源: {}", dbName);
        }
    }

    public void refreshDataSource() {
        JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);
        List<Map<String, Object>> dbList = jdbcTemplate.queryForList("SELECT db_name, database_url, database_account, database_password FROM system_data_source");
        for (Map<String, Object> map : dbList) {
            refreshDataSource(
                    map.get("db_name").toString().trim(),
                    map.get("database_url").toString().trim(),
                    map.get("database_account").toString().trim(),
                    map.get("database_password").toString().trim()
            );
        }
    }

    /**
     * 运行时动态刷新数据源（如新增租户等场景）
     */
    public void refreshDataSource(String dbName, String url, String username, String password) {
        DynamicRoutingDataSource ds = (DynamicRoutingDataSource) dataSource;
        if (ds.getDataSources().get(dbName) != null) {
            log.info("数据源已存在: {}", dbName);
            return;
        }
        DataSourceProperty dsp = new DataSourceProperty();
        dsp.setPoolName(dbName);
        dsp.setUrl(url);
        dsp.setUsername(username);
        dsp.setPassword(password);
        DataSource newDs = dataSourceCreator.createDataSource(dsp);
        ds.addDataSource(dbName, newDs);
        registerJdbcTemplateBean(dbName, newDs);
        log.info("运行时动态注册数据源: {}", dbName);
    }
}